package cheme.ProcessModel.ModelActions;

import java.util.List;

import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CommandStackEvent;
import org.eclipse.gef.commands.CompoundCommand;

import cheme.ProcessModel.Cmds.IChemeCommand;

public abstract class AbstractModelActionFactory implements IModelActionFactory
{
	public void stackChanged(CommandStackEvent event)
	{
		/*
		 * Need to append the post event prior to the main command's execution
		 */
		if(event.getDetail() != CommandStack.PRE_EXECUTE)
		{
			return;
		}

		if(event.getCommand() == null)
		{
			return;
		}
		
		process(event.getCommand());
	}
	
	public void process(Command command)
	{
		Command cmd = null;
		
		if(command instanceof IChemeCommand)
		{
			cmd = processCommand(command);
			
			if(null != cmd)
			{
				((IChemeCommand)command).append(cmd);
			}
		}
		else if(command instanceof CompoundCommand)
		{
			cmd = processCommand(command);
			
			if(null != cmd)
			{
				((CompoundCommand)command).add(cmd);
			}
		}
	}
	
	public Command processCommand(Command command)
	{
		Command cmd = null;
		
		if(command instanceof IChemeCommand)
		{
			cmd = processSimpleCommand((IChemeCommand)command);
		}
		else if(command instanceof CompoundCommand)
		{
			cmd = processCompoundCommand((CompoundCommand)command);
		}
		
		if(null != cmd && cmd instanceof CompoundCommand)
		{
			return ((CompoundCommand)cmd).unwrap();
		}
		
		return cmd;
	}
	
	public Command processCompoundCommand(CompoundCommand command)
	{
		CompoundCommand cmd = null;
		Command addCmd = null;
		
		for(Object child : command.getCommands())
		{
			addCmd = processCommand((Command)child);
				
			if(null != addCmd)
			{
				if(null == cmd)
				{
					cmd = new CompoundCommand(); 
				}
					
				cmd.add(addCmd);
			}
		}
		
		if(null != cmd)
		{
			return cmd.unwrap();
		}
		
		return cmd;
	}
	
	public Command processCompoundCommand(IChemeCommand command)
	{
		CompoundCommand cmd = null;
		Command addCmd = null;
		
		addCmd = processList(command.getPreCommands());
		if(addCmd != null)
		{
			if(null == cmd)
			{
				cmd = new CompoundCommand();
			}
			
			cmd.add(addCmd);
		}
		
		addCmd = processSimpleCommand(command);
		if(addCmd != null)
		{
			if(null == cmd)
			{
				cmd = new CompoundCommand();
			}
			
			cmd.add(addCmd);
		}
		
		addCmd = processList(command.getPostCommands());
		if(addCmd != null)
		{
			if(null == cmd)
			{
				cmd = new CompoundCommand();
			}
			
			cmd.add(addCmd);
		}
		
		if(null != cmd)
		{
			return cmd.unwrap();
		}
		
		return cmd;
	}
	
	Command processList(List<Command> list)
	{
		CompoundCommand cmd = null;
		Command addCmd = null;
		
		for(Object child : list)
		{
			addCmd = processCompoundCommand((IChemeCommand)child);
				
			if(null != addCmd)
			{
				if(null == cmd)
				{
					cmd = new CompoundCommand(); 
				}
					
				cmd.add(addCmd);
			}
		}
		
		if(null != cmd)
		{
			return cmd.unwrap();
		}
		
		return cmd;
	}
	
	public CompoundCommand processSimpleCommand(IChemeCommand command)
	{
		if(null == ((IChemeCommand)command).getSource())
		{
			return null;
		}
		
		return getActions((IChemeCommand)command);
	}
}
